/*
 * Copyright (C) 2010 Yury Kudryashov.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package name.kudryashov.collections;

import name.kudryashov.base.Argument;
import name.kudryashov.functions.Function2;

/**
 * Utility functions for working with arrays.
 */
public final class ExtArrays {
    // TODO foldLeft, reduceLeft, reduceRight, foreach, filter, exists, forAll etc.

    private ExtArrays() {}

    /**
     * Performs a "right folding" of the array applying the given function to each element
     * starting from the back of the array and keeping the function result.
     * <p>
     * {@code initial} value is passed to the first call of the function (with the last element), then the result
     * of the function's call is applied to the {@code last - 1} element etc. The final result is returned
     * from the function.
     * @param array array, not null
     * @param initial initial value
     * @param f folding function, not null
     * @param <T> type of element in the array
     * @param <R> type of the result
     * @return the folding result or the initial value if array is empty
     * @throws NullPointerException either {@code array} or {@code f} is empty
     */
    public static <T, R> R foldRight(T[] array, R initial, Function2<? super T, R, R> f) {
        Argument.requireNotNull(array, "array");
        Argument.requireNotNull(f, "f");
        R result = initial;
        for(int i = array.length - 1; i >= 0; i--) {
            result = f.apply(array[i], result);
        }
        return result;
    }

}
